Skip to content

Verified mainnet mining for macOS, Linux and native Windows - #14

Open
adamtpang wants to merge 12 commits into
Quantus-Network:mainfrom
adamtpang:codex/one-command-mining-9-9
Open

adamtpang wants to merge 12 commits into
Quantus-Network:mainfrom
adamtpang:codex/one-command-mining-9-9

Conversation

@adamtpang

@adamtpang adamtpang commented Sep 3, 2026

Copy link
Copy Markdown

Overview

One verified path to mine Quantus mainnet, on macOS, Linux, and native Windows, tested end to end on real hardware. It now includes a double-click window for people who never open a terminal.

This branch merges main (including #17's mainnet guide and #18) and repins everything to mainnet. It resolves the conflict this PR had with main.

Verified on real hardware

Windows 11 laptop, RTX 3070, mainnet, 2026-09-14:

Check Result
Node v1.0.1 Windows build Carries the mainnet chain spec, joins with peers, syncs from genesis (42k blocks in about 10 min)
Miner v4.2.0 Authenticates to the node, receives work, benchmarks 45.7 MH/s
Full installer run with a real wallet Setup, sync, status reporting MINING, stop, restart
Asset hashes Match GitHub's release digests; the node zip also matches the release's sha256sums file

Native Windows needs no WSL. On Windows the miner has to run natively anyway to reach the GPU driver.

What changed

Pinned pair and network

  • mining-compatibility.json: mainnet, node v1.0.1, miner v4.2.0, every URL and SHA-256 from the release digests.
  • Both installers accept only a mainnet manifest.
  • Intel macOS is refused with a clear message, because node v1.0.1 publishes no x86_64-apple-darwin build.
  • setup --force keeps the reward identity (the behaviour docs: point mining guide at Quantus mainnet #17 added). A Planck install moves to mainnet without asking for the recovery phrase again.

Native Windows installer (quantus-mining.ps1)

  • Twin of quantus-mining.sh: same commands, manifest, checksums, hidden phrase prompt, and status contract.
  • Parses and runs on Windows PowerShell 5.1, which ships with Windows.

Found by running it, fixed in both installers where relevant

  • status said "Synced" when isSyncing flickered false between import batches. It now also requires the block height to be within two of the best peer height.
  • The shell installer sources mining.conf, and config set wrote values unescaped, so a node name like $(command) would execute. Every editable value is now validated.
  • Setup named the node after the hostname without asking, and that name is public on telemetry. It now asks, and QUANTUS_NODE_NAME answers without a prompt.
  • Hash rate printed a raw log line. It is now one averaged number, with a warning when the miner goes quiet.
  • Windows: start hung forever when its output was captured, which is exactly how an agent runs it. Processes now launch without inheriting the caller's handles.
  • Windows: launched from PowerShell 7 or with captured output, setup died at the first checksum or at node-key generation. Both are fixed.
  • Windows: every hint now prints a command that can be pasted as-is.
  • Setup remembers a non-default install location, so later commands work without setting paths again.
  • Windows autostart on|off|status: a per-user login entry, no admin rights needed.
  • Windows setup checks the drive has the 100 GB the node guide requires, before any download or wallet input.
  • Removed the default "add a Defender exclusion" advice. Measured on a real sync, Defender used no CPU; weakening antivirus should not be a default fix.

Desktop launcher (preview): Start Quantus Mining.cmd + quantus-mining-app.ps1

  • A small window over the verified installer; no mining logic of its own.
  • First run: the 24 words go into a masked box, plus a public miner name, then one Start button. The phrase reaches the installer once, on standard input only.
  • Afterwards: plain status ("Mining", "Getting ready 76%"), Start and Stop, "start when I turn on the laptop", and a heat warning from the NVIDIA driver.
  • Earnings line: the reward address's real balance, read from the local node's System.Account storage, times the CoinGecko QTC price. No estimates.
  • "Run cooler" sets a new validated GPU_THROTTLE_MS, passed to the miner as --gpu-throttle-ms. Measured on the test laptop: 87 C with thermal slowdown active at 0 ms, versus 76 C with no slowdown at 30 ms, at about half the hash rate.

Docs, skill, agent prompt

  • Guide: a PowerShell download-and-verify block beside the curl one, a "Coming from Planck" section, and Windows rows in the recovery table.
  • Skill and agent prompt describe mainnet and route native Windows to the .ps1.

Validation

  • bun test: 44 pass, including PowerShell parse and behaviour tests, shell safety helpers, identity preservation, manifest pinning, and published-checksum byte checks.
  • bun run typecheck and bun run build pass.
  • The manual runs in the table above.

Needs an owner decision

  • The public manifest, scripts, and .sha256 files return 404 on docs.quantus.com until this merges. Until then the installer needs QUANTUS_COMPATIBILITY_URL pointed at a local copy.
  • The miner release publishes no checksum file (the chain release does). The manifest hash is the only pin; a sha256sums asset on miner releases would help.
  • minimumWindows/macOS/Linux in the manifest remain not-published.
  • The launcher is unsigned, so Windows SmartScreen warns on first run. Signing is the real fix.

Not in this PR

  • macOS and Linux autostart (launchd, systemd user units).
  • A QR hand-off from the wallet app, so desktop setup never needs the 24 words typed on a computer.

🤖 Generated with Claude Code

Pin one supported Planck node and miner pair in a machine-readable compatibility manifest.

Verify release checksums before installation, keep wallet recovery input local, add clear status and restart checks, and publish direct desktop preview downloads with platform verification commands.

Add automated compatibility, checksum, redaction, command, and documentation tests.
adamtpang and others added 11 commits September 5, 2026 14:01
The installer is published with a SHA-256 file, and a test asserts that the
checksum matches the exact bytes in the repository. On a Windows clone with
core.autocrlf=true, git rewrites the script to CRLF on checkout, the bytes no
longer match, and the test fails for a reason that has nothing to do with the
installer. The same rewrite would make a locally built docs site serve a
script whose checksum does not match its own .sha256.

.gitattributes now pins LF for the installers, their checksum files, and the
compatibility manifest. The four files are renormalized in the same change.

The bash-backed tests also stop spawning a login shell. bash -lc sources the
developer's profile, and anything it prints (a clear-screen escape, a greeting)
lands in the captured stdout and breaks exact-match assertions. --noprofile
--norc runs the same commands in a clean shell, which is what CI does anyway.

On this Windows machine the suite goes from 3 failures to 0 with no change to
what is being tested.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The guide told Windows users to open WSL2 or try the desktop app preview.
Neither is a working GPU path. Under WSL2 the miner's wgpu backend has no
reliable route to the host GPU, and the desktop app is a preview that does not
pin or verify what it downloads. Meanwhile the compatibility manifest already
carried Windows URLs and checksums for both binaries, and the chain's own
MINING.md documents the native MSVC node as supported.

Verified by hand on a Windows 11 laptop with an RTX 3070 before writing any
of this, using only the manifest's Windows assets:

  node v0.10.0     starts on Planck natively, no WSL, syncs at ~175 blocks/s,
                   writes miner-auth-token and miner-tls-cert-sha256
  miner v4.0.2     SHA-256 matches the manifest, benchmarks at 33.6 MH/s on
                   the discrete GPU, and against the node: authenticates,
                   registers, receives job 1, returns a Completed result
  key quantus      --scheme wormhole --words re-derives the same address and
                   inner hash from a phrase on stdin, so the hidden prompt works
  system_syncState exposes current and highest block over RPC on 9944

quantus-mining.ps1 is a twin of quantus-mining.sh, not a port of its text:
same commands (mine, setup, status, start, stop, restart, restart-check,
config, uninstall), same manifest fields, same fail-closed checks on network,
protocol, release URL, asset name and checksum, same pair probe on --help,
same hidden recovery-phrase prompt with the phrase passed on stdin only, same
owner-only files for the config and the reward preimage, same redaction in
status, same status contract. Where Windows differs it says so in a comment.

Two things the Windows status does that the shell one does not yet:

  - While syncing, it shows block, target, rate and time left, measured over a
    five second window from system_syncState. Full sync is the only mode this
    node supports (warp reports no provider, fast refuses on archive nodes),
    and it takes one to a few hours. Saying "Syncing" for two hours is the
    single worst part of the newcomer experience; a number that moves is not.
  - It detects the Windows Defender stall MINING.md warns about (peers
    connected, block number not moving) and prints the one-time elevated
    command as the single recovery action, instead of leaving the user to
    diagnose it. The exclusion itself is left to the user: it is a security
    setting, and the installer never elevates.

The guide gains a PowerShell download-and-verify block beside the curl one,
opens with "open a shell" instead of "open WSL2", and gets two Windows rows in
the recovery table. The skill routes native Windows to the .ps1 and no longer
sends anyone to the app preview. The shell installer's unsupported-OS message
now names the .ps1. quantus-mining.ps1.sha256 is published beside it, and the
shell installer's checksum is regenerated for its one changed line.

mining.conf.example still showed INNER_HASH inside the public config, which
the installers stopped doing in this branch; it now matches what they write.

Tests: seven new cases. Static ones check the command contract, the manifest
keys the script reads, that the phrase never reaches the command line or the
config, that the guide and skill point Windows at the .ps1, and that the
published checksum matches the bytes. Behaviour ones parse the script with
PowerShell's own parser and exercise manifest loading, protocol classification,
fail-closed checksums and redaction by dot-sourcing it; they run on pwsh or
Windows PowerShell and skip where neither exists, so a Linux runner without
pwsh still passes the static half. Parsed clean on both PowerShell 7.6 and
Windows PowerShell 5.1, which ships with Windows.

Not done here: a run of the installer's own download path on a clean Windows
machine, which needs the 23 MB node archive fetched through the script rather
than by hand. Everything downstream of that download is what was verified
above.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Publish a plain Markdown setup prompt and link it before manual prerequisites. Reuse the pinned compatibility manifest and verified installer flow; pause for private wallet input and distinguish syncing from mining.

Add endpoint/link/safety tests and allow 20 seconds for the existing five-process PowerShell test. Validation: typecheck, 23 passing tests, production build, published artifact hash and guide-link checks. No live mining validation performed.
…xclusions

Windows setup now measures free space on the drive that will hold the node
database (QUANTUS_NODE_DATA_PATH, or the default) before any directory is
created, any binary is downloaded, or any wallet input is requested, and
refuses below the storage minimum in the pinned node guide. A new preflight
command runs the platform and storage checks on their own, with no secrets and
no downloads, so a user can find out before starting.

The stall recovery no longer tells users to add a Windows Defender exclusion.
Measured on a real sync, Defender used no CPU while blocks imported, so the
exclusion was advice for a cause that was not diagnosed. Weakening a security
control is not a safe default fix. Status, help, guide and skill now point at
disk space, peers and disk activity instead.

"No hash rate after sync" no longer defaults to reinstalling, which would make
the user repeat wallet entry without anyone finding out what failed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Main moved the mining guide to mainnet in Quantus-Network#17 and retired Planck. This branch
still pinned the Planck pair (node v0.10.0, miner v4.0.2) and both installers
refused any network but Planck, so as merged they would have installed and
synced a retired chain.

Conflicts in the guide, skill, installer and config example are resolved by
keeping this branch's verified installers and short guide, then carrying main's
mainnet content into them rather than keeping two descriptions of setup:

  - The manifest now pins node v1.0.1 and miner v4.2.0 on mainnet, with every
    URL and SHA-256 taken from GitHub's own release digests. The node's
    Windows digest also matches the release's sha256sums file.
  - Both installers accept only a mainnet manifest.
  - setup --force on an existing install keeps the reward identity, which is
    the behaviour main added. Here the preimage lives in its owner-only
    rewards-inner-hash file, so main's regression test is adapted to assert
    that file is untouched and that the preimage is never written into the
    public config. It moves a Planck install to mainnet without asking for the
    recovery phrase again.
  - A Planck config is named as the retired testnet when start refuses it.
  - Guide gains "Coming from Planck", including main's warning never to pass
    --force-authoring. Skill and agent prompt describe mainnet and stop saying
    tokens have no value.
  - Node v1.0.1 publishes no Intel macOS build, so that platform is dropped
    from the manifest and refused with a clear message rather than paired with
    a node that does not exist.
  - The desktop app page now says that release was built for Planck and is not
    verified for mainnet funds.

Verified on a Windows 11 laptop with an RTX 3070 before changing the pin: the
v1.0.1 node carries the mainnet chain spec (id mainnet, 7 bootnodes), joins
mainnet with peers and writes its miner auth files; miner v4.2.0 authenticates,
connects and waits for work, and benchmarks at 45.7 MH/s. Then the real
installer, end to end against mainnet with a throwaway identity: setup -Force
downloaded and verified both assets and moved a Planck config to mainnet with
the identity kept; start, status and stop all worked; status reported "block
32,055 of 42,203 (76.0%), 84 blocks/s, about 2 min left, 7 peers". Stopped
before tip, 0 blocks sealed.

That run found two Windows bugs, fixed here:

  - start never returned when its output was captured. Start-Process with
    redirection passes the script's standard handles to the node and miner,
    which then hold the caller's pipe open forever. Every agent-driven setup
    would hang there. Processes now launch through WMI, which inherits nothing,
    with cmd.exe doing the log redirection; PID files still hold the real node
    and miner PIDs. The same piped start now returns in 12 seconds.
  - config show and config set always printed usage: the function's parameter
    was named $Args, PowerShell's automatic variable, which shadowed it.

28 tests pass (4 new: missing-platform refusal, non-mainnet refusal, identity
preservation, mainnet wording), typecheck clean, docs build passes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…c by height

Three problems found on a first real mainnet run.

Setup named the node after the computer (quantus-<hostname>) without asking.
That name is public on the telemetry dashboard, so a user could publish their
machine name, and renaming meant a separate config command and a restart. Both
installers now ask for it, with that default shown, and explain that it is
public and should not be a real name. QUANTUS_NODE_NAME answers the question
without a prompt, and a session with no terminal (an agent, CI) takes the
default rather than blocking.

The shell installer reads mining.conf back with source, and config set wrote
values into it unchecked, with the numeric keys unquoted. A NODE_NAME of
$(command) or a CPU_WORKERS of "1; command" would run on the next invocation.
Every editable value is now validated before it is written: names are 3-32
lowercase letters, digits and hyphens; CPU_WORKERS and GPU_DEVICES are 0-256;
MINER_LISTEN_PORT is 1024-65535. PowerShell applies the same rules.

status reported Synced whenever system_health said isSyncing was false. The
node reports that for a moment between import batches, so status could say
Synced at 40 percent. Synced now also requires the current block to be within
two of the highest block peers report (system_syncState), in both installers.
Checked against a live node mid-sync: raw isSyncing flickered, status held
"Syncing, block 41,145 of 42,290 (97.3%)".

32 tests pass, 4 new. Parses clean on Windows PowerShell 5.1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…s autostart

Three more gaps from a first real mainnet run.

Hash rate. status printed the last matching miner log line verbatim, timestamp
and module name included, which reads as an error to anyone who does not know
the log format. It now shows one number. Each GPU worker logs every search as
"H hashes in T s", and a search a new block cuts short can be two seconds long,
so a single line swung between 25 and 37 MH/s on the same machine within a
minute. The rate is total hashes over total seconds per worker across the last
three minutes, summed over workers. No search in that window reports "miner is
not working now" and keeps the overall state out of MINING, even if the miner
process is still alive. Measured against a live mainnet miner log: 27.1 MH/s.

Install location. A user who installs to another drive (the only option on a
laptop with a full system disk) had to set QUANTUS_MINING_DIR and
QUANTUS_NODE_DATA_PATH again in every new shell, or every command acted on an
empty default install. Setup now records both paths in a small per-user file
(%LOCALAPPDATA%\quantus-mining\location, or ~/.config/quantus-mining/location),
which later commands read when those variables are unset. The file is parsed
line by line, never sourced or executed, and entries that are not absolute
paths or contain quotes, $ or backticks are ignored. Uninstall removes it when
it points at the install being removed. Setup also keeps a copy of the exact
installer script beside the install.

Autostart (Windows). Mining stopped at every reboot until someone re-ran it.
New command: autostart on|off|status. It writes one per-user login entry
(HKCU Run, no administrator rights), which runs the installed script's start
hidden, 20 seconds after sign-in so a USB data drive and the network are up,
logging to logs\autostart.log. Interactive Windows setup asks once, defaulting
to yes; a non-interactive setup never enables it. Uninstall removes the entry.
The macOS and Linux equivalents (launchd, systemd user units) are not in this
change.

37 tests pass, 5 new, including autostart on and off against a throwaway
registry key rather than the real login list.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Hints said 'quantus-mining.ps1 autostart off', which PowerShell refuses to run by bare name. Every hint now prints the full invocation of the installed copy, found on a first real run.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
"Start Quantus Mining.cmd" opens quantus-mining-app.ps1, a small window over
the verified installer. It adds no mining logic: it collects two answers, runs
the installer, and turns its status into plain words.

First run: one screen asks for the 24 secret words (masked, with a "show while
I type" box for checking typos) and a public miner name, with one Start button.
Progress reads "Downloading the Quantus software (1 of 2)", not installer
output. Afterwards it turns on autostart, puts a Quantus Mining icon on the
desktop pointing at a copy kept beside the install, and switches to the only
screen used again: Mining / Getting ready (with percent and time left) / Not
mining / Stuck, the speed, Start and Stop, a "start when I turn on the laptop"
box, and a plain heat warning when the NVIDIA driver reports thermal slowdown.

The phrase goes to the installer once, on standard input, the same channel the
node reads it from; it is never in arguments, environment variables, files or
logs. The installer reads a redirected stdin instead of prompting.

Testing the handoff for real found two installer bugs that would have stopped
any captured or launcher-driven setup, both fixed here:

  - Launched from a PowerShell 7 window, Windows PowerShell inherits PS7's
    module paths first and cannot find its own Get-FileHash, so setup died at
    the first checksum. PS7 paths are now dropped on startup.
  - With output captured, Windows PowerShell under Stop turns a native
    program's stderr line into a terminating error. The node prints its key ID
    to stderr, so setup died generating the node key. Native calls now run
    under Continue and are judged by exit code.

Verified on a Windows 11 laptop: a throwaway 24-word phrase handed over on
stdin produced the matching reward address in an isolated install, without
touching the real install's location file or login entry; both screens render
against a live mainnet miner ("Mining, Speed: 29.1 MH/s", heat warning shown).
41 tests pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Earnings show the reward address's real balance, read from the local node's System.Account storage (address decoded and checksum-verified in-app), times the CoinGecko QTC price. A blocks-won counter was left out: the node's result log line marks a finished search, not a won block. Run cooler sets the new validated GPU_THROTTLE_MS installer key, passed to the miner as --gpu-throttle-ms. Measured on an RTX 3070 laptop on mainnet: 0 ms 87 C, 84 W, 37.9 MH/s, thermal slowdown active; 30 ms 76 C, 61 W, 18.0 MH/s, no slowdown; 80 ms 76 C, 7.9 MH/s. 30 ms is the default.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Local agent notes came in with the earlier onboarding commits and do not belong in this change.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@adamtpang adamtpang changed the title Make mining a verified one-command path Verified mainnet mining for macOS, Linux and native Windows Sep 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant